home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Almathera Ten Pack 3: CDPD 3
/
Almathera Ten on Ten - Disc 3: CDPD3.iso
/
fish
/
001-100
/
001-025
/
020
/
speechterm
/
term.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-03-17
|
22KB
|
862 lines
#include <stdio.h>
#include <exec/types.h>
#include <exec/exec.h>
#include <libraries/dos.h>
#include <libraries/dosextens.h>
#include <devices/serial.h>
#define MAX_CHARS 102
#define SECSIZ 0x80
#define TTIME 30
#define BufSize 0x1000
#define ERRORMAX 10
#define RETRYMAX 10
#define SOH 1
#define EOT 4
#define ACK 6
#define CTRLQ (char)17
#define CTRLS (char)19
#define NAK 21
static char bufr[BufSize];
static int fd, timeout = FALSE;
static long bytes_xferred;
static int oktosay = 1;
/*
* External functions
*/
extern unsigned char *stpblk();
extern unsigned char *AllocMem();
extern struct MsgPort *CreatePort();
extern struct FileHandle *Open();
/*
* forward references
*/
int define_function_key(), end(), help(), offline(), online(), sb(), rb(),
gfxoff(), speechon(), speechoff();
/*
* Tables
*/
struct {
unsigned char *cmdname;
int (*cmdfunc)();
} command_table[] = {
(unsigned char *)"define", &define_function_key,
(unsigned char *)"def", &define_function_key,
(unsigned char *)"end", &end,
(unsigned char *)"help", &help,
(unsigned char *)"online", &online,
(unsigned char *)"on", &online,
(unsigned char *)"offline", &offline,
(unsigned char *)"off", &offline,
(unsigned char *)"gfxoff", &gfxoff,
(unsigned char *)"sb", &sb,
(unsigned char *)"rb", &rb,
(unsigned char *)"speechon", &speechon,
(unsigned char *)"speechoff", &speechoff,
(unsigned char *)"\0", &help,
};
unsigned char *help_messages[] = {
"sb = send file using Xmodem",
"rb = receive file using Xmodem",
"def = define a function key",
"define = define a function key",
"end = exit the program",
"help = print this list",
"online = enter or re-enter terminal mode",
"offline = terminate communication",
"gfxoff = terminate graphics",
"speechon = permit speech",
"speechoff = forbid speech",
0};
unsigned char *function_key_definitions[20] = {
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0
};
/*
* Globals
*/
unsigned char work[512];
unsigned char buf[512];
unsigned char iobuf[1024];
int num_of_chars, no_io;
/*
* Terminal globals
*/
struct FileHandle *terminal_infp;
struct FileHandle *terminal_outfp;
/*
* Terminal emulator stuff
*/
struct Message *mymessage;
struct IOExtSer *ModemReadRequest;
struct IOExtSer *ModemWriteRequest;
unsigned char *WelcomeMessage = "Entering Terminal Mode\nUse ^C for command mode\n";
unsigned char *GoodbyeMessage = "Disconnected\n";
unsigned char *OfflineMessage = "--- Offline ---\n";
unsigned char *OnlineMessage = "--- Online ---\n";
unsigned char rs_in[2], rs_out[2];
int bdoneflag = 0;
int TermEcho = 0;
int modem_online = 0;
static int gfx_flag;
main(argc, argv)
int argc;
unsigned char *argv[];
{
gfx_flag = 0;
num_of_chars = 0;
no_io = 0;
sprintf(work, "Raw:0/0/640/200/Terminal");
terminal_infp = Open(work, MODE_NEWFILE);
if (terminal_infp == 0) {
printf("Can't open window\n");
exit(1);
}
terminal_outfp = terminal_infp;
sprintf(work, "\033[0x\033[0y\033[25t\033[80u\014");
WriteWork();
while (1) {
Write(terminal_outfp, "\033[7mterm:\033[m ", 13);
getcommand(buf);
CommandInterpreter(buf);
}
}
WriteWork() {
Write(terminal_outfp, work, strlen(work));
}
CommandInterpreter(command)
unsigned char *command;
{
int i;
command = stpblk(command);
/*
* Scan through the command table for the string and invoke the function
* to do the actual work of the command. Each of these commands is
* defined below, and the functions each take a pointer to the
* string containing the arguments passed the command line.
*/
for (i=0; command_table[i].cmdname[0] != '\0'; i++)
if (strncmp(command, command_table[i].cmdname,
strlen(command_table[i].cmdname)) == 0) {
(*command_table[i].cmdfunc)
(stpblk(&command[strlen(command_table[i].cmdname)]));
goto FinishedCommand;
}
/*
* Not found, so look for it on the disk.
*/
executive(stpblk(&command[0]));
FinishedCommand:
; /* Labels MUST be attached to some statement; even if the null stmt */
}
executive(s)
unsigned char *s;
{
if (!Execute(s, 0, terminal_outfp))
printf("%d\n", IoErr());
}
define_function_key(s)
unsigned char *s;
{
int i;
if (s[0] == '\0')
for (i=0; i<20; i++) {
if (function_key_definitions[i]) {
sprintf(work, "F%-2d = %s\n", i+1, function_key_definitions[i]);
WriteWork();
}
}
else if (s[0] == 'f' || s[0] == 'F') {
s++;
i = atoi(s);
if (i < 1 || i > 20) {
sprintf(work, "%c[36mInvalid function key%c[0m\n", 0x1b, 0x1b);
WriteWork();
} else {
i--;
if (function_key_definitions[i])
FreeMem(function_key_definitions[i], strlen(function_key_definitions[i])+1);
while (isdigit(*s))
s++;
s = stpblk(s);
if (*s != '\0') {
function_key_definitions[i] = AllocMem(strlen(s)+1, MEMF_PUBLIC|MEMF_CLEAR);
if (function_key_definitions[i] == 0) {
sprintf(work, "%c[36mDefine Error: not enough memory%c[0m\n",
0x1b, 0x1b);
WriteWork();
} else
strcpy(function_key_definitions[i], s);
}
}
} else {
sprintf(work,
"%c[36mDefine Error: invalid function key specified%c[0m\n",
0x1b, 0x1b);
WriteWork();
}
}
end(s)
unsigned char *s;
{
if (modem_online) {
sprintf(work, "%c[36mTerminal Mode Error: Modem still online%c[0m\n",
0x1b, 0x1b);
WriteWork();
} else {
if (gfx_flag == 1)
terminate();
Close(terminal_outfp);
exit(0);
}
}
help(s)
unsigned char *s;
{
int i;
sprintf(work,"%c[7m MyCli Help %c[0m\n", 0x1b, 0x1b);
WriteWork();
for (i=0; help_messages[i]; i++) {
sprintf(work, "%s\n", help_messages[i]);
WriteWork();
}
sprintf(work, "%c[7m End of Help %c[0m\n", 0x1b, 0x1b);
WriteWork();
}
gfxoff()
{
if (gfx_flag == 1)
terminate();
gfx_flag = 0;
}
speechon()
{
oktosay = 1;
}
speechoff()
{
oktosay = 0;
}
offline(s)
unsigned char *s;
{
modem_online = 0;
say_string((char*)0, 1);
}
online(s)
unsigned char *s;
{
modem_online = !0; /* signal that modem is live !!! */
if (initialize()) { /* set baud rate, etc. */
Write(terminal_outfp, WelcomeMessage, strlen(WelcomeMessage));
while (modem_online) {
bdoneflag = 0; /* terminal mode on flag */
Write(terminal_outfp, OnlineMessage, strlen(OnlineMessage));
while (!bdoneflag) {
check_keyboard();
check_modem();
if (bdoneflag || num_of_chars > MAX_CHARS || no_io > 0) {
if (num_of_chars > 0) {
Write(terminal_outfp, iobuf, num_of_chars);
num_of_chars = 0;
}
}
}
Write(terminal_outfp, OfflineMessage, strlen(OfflineMessage));
Write(terminal_outfp, "\033[7mterm:\033[m ", 13);
getcommand(buf);
CommandInterpreter(buf);
}
cleanup();
}
modem_online = 0;
}
getcommand(s)
unsigned char *s;
{
unsigned char c;
unsigned col;
col = 0;
while (1) {
Read(terminal_infp, &c, 1);
switch(c) {
case 8:
if (col) {
c = 8;
Write(terminal_outfp, &c, 1);
c = ' ';
Write(terminal_outfp, &c, 1);
c = 8;
Write(terminal_outfp, &c, 1);
col--;
}
continue;
case 10:
case 13:
sprintf(work, "\n");
WriteWork();
s[col++] = '\0';
break;
case 0x1b:
case 24:
while (col) {
c = 8;
Write(terminal_outfp, &c, 1);
c = ' ';
Write(terminal_outfp, &c, 1);
c = 8;
Write(terminal_outfp, &c, 1);
col--;
}
continue;
case 0x9b:
if (process_event(&s[col])) {
strcat(s, "\n");
Write(terminal_outfp, &s[col], strlen(&s[col]));
break;
}
continue;
default:
s[col++] = c;
Write(terminal_outfp, &c, 1);
continue;
}
break;
}
}
/*
* this function converts an incoming ANSI escape sequence
* and processes it. A buffer is passed where any function
* key expansion is to take place. If the buffer is modified
* for any reason, this function returns true.
*/
process_event(cmd_line)
unsigned char *cmd_line;
{
int i;
unsigned char c;
char event_buffer[32];
i = 0;
while (1) {
Read(terminal_infp, &c, 1);
event_buffer[i] = c;
if (c == '~' || c == '|' || c == 'A' || c == 'B' || c == 'C' || c == 'D')
break;
i++;
}
event_buffer[i+1] = '\0';
if (event_buffer[i] == '~') {
if (event_buffer[0] == '?') {
strcpy(cmd_line, "help");
return !0;
} else if (isdigit(event_buffer[0])) {
if (function_key(atoi(event_buffer), cmd_line))
return !0;
else if (atoi(event_buffer) == 6)
bdoneflag = !0;
}
} else if (i == 0 && (event_buffer[0] >= 'A' && event_buffer[0] <= 'D')) {
cmd_line[0] = '\033';
cmd_line[1] = event_buffer[0];
cmd_line[2] = '\000';
return !0;
}
return 0;
}
/*
* if a definition for the function key fkey exists (0-19), then
* the translation for the function key is copied to the string
* s, and this function returns !0. Otherwise, now translation
* exists, and this function returns 0.
*/
function_key(fkey, s)
int fkey;
unsigned char *s;
{
int i;
if (function_key_definitions[fkey] != 0) {
for (i=0; function_key_definitions[fkey][i] != '\0'; i++)
s[i] = function_key_definitions[fkey][i];
s[i] = '\0';
return !0;
}
return 0;
}
initialize() {
ModemReadRequest = (struct IOExtSer *)AllocMem(sizeof(*ModemReadRequest),
MEMF_PUBLIC | MEMF_CLEAR);
ModemReadRequest->io_SerFlags = SERF_SHARED | SERF_XDISABLED;
ModemReadRequest->IOSer.io_Message.mn_ReplyPort =
CreatePort("Read_RS",0);
if (OpenDevice(SERIALNAME, NULL, ModemReadRequest, NULL)) {
sprintf(work, "%c[36mCan't open serial read device%c[0m\n",
0x1b, 0x1b);
WriteWork();
DeletePort(ModemReadRequest->IOSer.io_Message.mn_ReplyPort);
FreeMem(ModemReadRequest, sizeof(*ModemReadRequest));
return 0;
}
ModemReadRequest->IOSer.io_Command = CMD_READ;
ModemReadRequest->IOSer.io_Length = 1;
ModemReadRequest->IOSer.io_Data = (APTR) &rs_in[0];
ModemWriteRequest = (struct IOExtSer *)AllocMem(sizeof(*ModemWriteRequest),
MEMF_PUBLIC | MEMF_CLEAR);
ModemWriteRequest->io_SerFlags = SERF_SHARED | SERF_XDISABLED;
ModemWriteRequest->IOSer.io_Message.mn_ReplyPort =
CreatePort("Write_RS",0);
if (OpenDevice(SERIALNAME, NULL, ModemWriteRequest, NULL)) {
sprintf(work, "%c[36mCan't open serial write device%c[0m\n",
0x1b, 0x1b);
WriteWork();
DeletePort(ModemReadRequest->IOSer.io_Message.mn_ReplyPort);
FreeMem(ModemReadRequest, sizeof(*ModemReadRequest));
DeletePort(ModemWriteRequest->IOSer.io_Message.mn_ReplyPort);
FreeMem(ModemWriteRequest, sizeof(*ModemWriteRequest));
return 0;
}
ModemWriteRequest->IOSer.io_Command = CMD_WRITE;
ModemWriteRequest->IOSer.io_Length = 1;
ModemWriteRequest->IOSer.io_Data = (APTR) &rs_out[0];
ModemReadRequest->io_SerFlags = SERF_SHARED | SERF_XDISABLED;
ModemReadRequest->io_Baud = 1200;
ModemReadRequest->io_ReadLen = 8;
ModemReadRequest->io_WriteLen = 8;
ModemReadRequest->io_CtlChar = 1L;
ModemReadRequest->IOSer.io_Command = SDCMD_SETPARAMS;
DoIO(ModemReadRequest);
ModemReadRequest->IOSer.io_Command = CMD_READ;
BeginIO(ModemReadRequest);
return !0;
}
cleanup() {
CloseDevice(ModemReadRequest);
DeletePort(ModemReadRequest->IOSer.io_Message.mn_ReplyPort);
FreeMem(ModemReadRequest, sizeof(*ModemReadRequest));
CloseDevice(ModemWriteRequest);
DeletePort(ModemWriteRequest->IOSer.io_Message.mn_ReplyPort);
FreeMem(ModemWriteRequest, sizeof(*ModemWriteRequest));
Write(terminal_outfp, GoodbyeMessage, strlen(GoodbyeMessage));
}
check_keyboard()
{
unsigned char *pc;
if (WaitForChar(terminal_infp, 1)) {
Read(terminal_infp, &rs_out[0], 1);
switch ((unsigned char)rs_out[0]) {
case 0x9b: /* ANSI keyboard stuff */
if (process_event(&buf[0])) { /* send the translation */
pc = &buf[0];
while (*pc != '\0') {
rs_out[0] = *pc++;
if (TermEcho)
Write(terminal_outfp, &rs_out[0], 1);
DoIO(ModemWriteRequest);
check_modem();
}
}
break;
case 0x05: /* toggle keystroke echo */
TermEcho = !TermEcho;
sprintf(work, "%c[36mEcho %s%c[0m\n", 0x1b, TermEcho?"ON":"OFF",
0x1b);
WriteWork();
break;
default:
if (TermEcho)
Write(terminal_outfp, &rs_out[0], 1);
DoIO(ModemWriteRequest);
}
}
}
/*
* Check to see if the Read Request IO has completed from the modem.
*/
check_modem()
{
static int sayflag = 0;
static char saystring[133];
static int sayind = 0;
static int escape_sequence = 0;
if (CheckIO(ModemReadRequest)) {
WaitIO(ModemReadRequest);
rs_in[0] &= 0x7f;
if (rs_in[0] == '\001' && oktosay == 1) {
sayflag = 1;
BeginIO(ModemReadRequest);
return;
}
if (oktosay == 1 && sayflag) {
if (rs_in[0] >= ' ' && rs_in[0] < (char)127) {
saystring[sayind++] = rs_in[0];
} else {
Write(terminal_outfp, iobuf, num_of_chars);
rs_out[0] = CTRLS;
DoIO(ModemWriteRequest);
num_of_chars = 0;
saystring[sayind++] = (char)0;
say_string(saystring,0);
sayind = 0;
sayflag = 0;
rs_out[0] = CTRLQ;
DoIO(ModemWriteRequest);
}
}
if (rs_in[0] == '\033') {
escape_sequence = 1;
} else if (escape_sequence == 1) {
if (rs_in[0] == 'G') {
Graphics();
} else {
iobuf[num_of_chars++] = '\033';
iobuf[num_of_chars++] = rs_in[0];
no_io = 0;
}
escape_sequence = 0;
} else {
iobuf[num_of_chars++] = rs_in[0];
no_io = 0;
}
BeginIO(ModemReadRequest);
} else {
no_io++;
}
}
sendchar(ch)
int ch;
{
rs_out[0] = ch;
DoIO(ModemWriteRequest);
}
readchar()
{
unsigned char c;
int rd,ch;
rd = FALSE;
while (rd == FALSE) {
if(CheckIO(ModemReadRequest)) {
WaitIO(ModemReadRequest);
ch=rs_in[0];
rd = TRUE;
BeginIO(ModemReadRequest);
}
}
if (rd == FALSE) {
timeout = TRUE;
emits("\nTimeout Waiting For Character\n");
}
c = ch;
return(c);
}
rb(file)
char *file;
{
int firstchar, sectnum, sectcurr, sectcomp, errors, errorflag;
unsigned int checksum, j, bufptr,i;
char numb[10];
bytes_xferred = 0L;
i = 10;
if ((fd = creat(file, 0)) < 0) {
emits("Cannot Open File\n");
return FALSE;
} else
emits("Receiving File\n");
timeout=FALSE;
sectnum = errors = bufptr = 0;
sendchar(NAK);
firstchar = 0;
while (firstchar != EOT && errors != ERRORMAX) {
errorflag = FALSE;
do {
firstchar = readchar();
if (timeout == TRUE)
return FALSE;
}
while (firstchar != SOH && firstchar != EOT);
if (firstchar == SOH) {
emits("Getting Block ");
stci_d(numb,sectnum,i);
emits(numb);
emits("...");
sectcurr = readchar();
if (timeout == TRUE)
return FALSE;
sectcomp = readchar();
if (timeout == TRUE)
return FALSE;
if ((sectcurr + sectcomp) == 255) {
if (sectcurr == (sectnum + 1 & 0xff)) {
checksum = 0;
for (j = bufptr; j < (bufptr + SECSIZ); j++) {
bufr[j] = readchar();
if (timeout == TRUE)
return FALSE;
checksum = (checksum + bufr[j]) & 0xff;
}
if (checksum == readchar()) {
errors = 0;
sectnum++;
bufptr += SECSIZ;
bytes_xferred += SECSIZ;
emits("verified\n");
if (bufptr == BufSize) {
bufptr = 0;
if (write(fd, bufr, BufSize) == EOF) {
emits("\nError Writing File\n");
return FALSE;
};
};
sendchar(ACK);
} else {
errorflag = TRUE;
if (timeout == TRUE)
return FALSE;
}
} else {
if (sectcurr == (sectnum & 0xff)) {
emits("\nReceived Duplicate Sector\n");
sendchar(ACK);
} else
errorflag = TRUE;
}
} else
errorflag = TRUE;
}
if (errorflag == TRUE) {
errors++;
emits("\nError\n");
sendchar(NAK);
}
};
if ((firstchar == EOT) && (errors < ERRORMAX)) {
sendchar(ACK);
write(fd, bufr, bufptr);
write(fd, "\n", 1);
close(fd);
return TRUE;
}
return FALSE;
}
sb(file)
char *file;
{
int sectnum, bytes_to_send, size, attempts, c, i;
unsigned checksum, j, bufptr;
char numb[10];
timeout=FALSE;
bytes_xferred = 0;
i = 10;
if ((fd = open(file, 1)) < 0) {
emits("Cannot Open Send File\n");
return FALSE;
} else
emits("Sending File\n");
attempts = 0;
sectnum = 1;
j=1;
while (((c = readchar()) != NAK) && (j++ < ERRORMAX));
if (j >= (ERRORMAX)) {
emits("\nReceiver not sending NAKs\n");
return FALSE;
};
while ((bytes_to_send = read(fd, bufr, BufSize)) && attempts != RETRYMAX)
{
if (bytes_to_send == EOF) {
emits("\nError Reading File\n");
return FALSE;
};
bufptr = 0;
while (bytes_to_send > 0 && attempts != RETRYMAX) {
attempts = 0;
do {
sendchar(SOH);
sendchar(sectnum);
sendchar(~sectnum);
checksum = 0;
size = SECSIZ <= bytes_to_send ? SECSIZ : bytes_to_send;
bytes_to_send -= size;
for (j = bufptr; j < (bufptr + SECSIZ); j++)
if (j < (bufptr + size)) {
sendchar(bufr[j]);
checksum += bufr[j];
} else {
sendchar(0);
}
sendchar(checksum & 0xff);
attempts++;
c = readchar();
if (timeout == TRUE)
return FALSE;
} while ((c != ACK) && (attempts != RETRYMAX));
bufptr += size;
bytes_xferred += size;
emits("Block ");
stci_d(numb,sectnum,i);
emits(numb);
emits(" sent\n");
sectnum++;
}
}
close(fd);
if (attempts == RETRYMAX) {
emits("\nNo Acknowledgment Of Sector, Aborting\n");
return FALSE;
} else {
attempts = 0;
do {
sendchar(EOT);
attempts++;
} while ((readchar() != ACK) && (attempts != RETRYMAX) && (timeout == FALSE));
if (attempts == RETRYMAX)
emits("\nNo Acknowledgment Of End Of File\n");
};
return TRUE;
}
emits(embuf)
char *embuf;
{
Write(terminal_outfp, embuf, strlen(embuf));
}
Graphics()
{
char buf[82], *gr_buf;
int gr_len, r, g, b, color, x1, y1, x2, y2;
int polx[256], poly[256], n, clip, xmin, ymin, xmax, ymax;
int i;
if (gfx_flag == 0) {
gfx_flag = 1;
initialise();
} else
get_screen();
rs_out[0] = CTRLS;
DoIO(ModemWriteRequest);
BeginIO(ModemReadRequest);
for(;;) {
gr_len = 0;
buf[0] = (char)0;
gr_buf = &(buf[1]);
while(gr_buf[gr_len-1] != '\015') {
if (CheckIO(ModemReadRequest)) {
WaitIO(ModemReadRequest);
rs_in[0] &= 0x7f;
if (rs_in[0] != '\012') {
gr_buf[gr_len++] = rs_in[0];
}
BeginIO(ModemReadRequest);
} else {
rs_out[0] = CTRLQ;
DoIO(ModemWriteRequest);
}
}
rs_out[0] = CTRLS;
DoIO(ModemWriteRequest);
gr_buf[gr_len-1] = (char)0;
switch (gr_buf[0]) {
case 'T':
/* terminate(); */
put_screen();
rs_out[0] = CTRLQ;
DoIO(ModemWriteRequest);
return;
case 'C':
sscanf(&(gr_buf[1]), "%d%d%d%d", &color, &r, &g, &b);
define_color(color, r, g, b);
if (check_user_action() == -1) {
put_screen();
return;
}
break;
case 'L':
sscanf(&(gr_buf[1]), "%d%d%d%d%d", &x1, &y1, &x2, &y2, &color);
draw(x1, y1, x2, y2, color);
if (check_user_action() == -1) {
put_screen();
return;
}
break;
case 'P':
sscanf(&(gr_buf[1]), "%d%d%d%d%d%d%d", &n, &color, &clip,
&xmin, &ymin, &xmax, &ymax);
for (i=0; i<n; i++) {
gr_len = 0;
buf[0] = (char)0;
gr_buf = &(buf[1]);
while(gr_buf[gr_len-1] != '\015') {
if (CheckIO(ModemReadRequest)) {
WaitIO(ModemReadRequest);
rs_in[0] &= 0x7f;
if (rs_in[0] != '\012') {
gr_buf[gr_len++] = rs_in[0];
}
BeginIO(ModemReadRequest);
} else {
rs_out[0] = CTRLQ;
DoIO(ModemWriteRequest);
}
}
gr_buf[gr_len-1] = (char)0;
sscanf(gr_buf,"%d%d", &(polx[i]), &(poly[i]));
}
rs_out[0] = CTRLS;
DoIO(ModemWriteRequest);
/* poly_draw(polx, poly, n, color, clip, xmin, ymin, xmax, ymax); */
if (check_user_action() == -1) {
put_screen();
return;
}
break;
}
}
}